/**
 * @file 74hc595.h
 * @brief 
 * @author mayh
 * @version 1.0
 * @date 2024-02-21
 * 
 * @copyright Copyright (c) 2024  cspro.
 * 
 * @par 修改日志:
 * 2024-02-21  创建文件,封装串转并功能函数
 */
#ifndef _74HC595_H__
#define _74HC595_H__
#include <stdint.h>
#include "gd32f4xx_gpio.h"
#define SETBIT(x,y) (x|=(1<<(7-y)))
#define CLRBIT(x,y) (x&=~(1<<(7-y)))

#define PCA9555_SETBIT(x,y) (x|=(1<<y))
#define PCA9555_CLRBIT(x,y) (x&=~(1<<y))

#define BIT0 0x01
#define BIT1 0x02
#define BIT2 0x04
#define BIT3 0x08
#define BIT4 0x10
#define BIT5 0x20
#define BIT6 0x40
#define BIT7 0x80


//定义芯片的串行输入以及时钟引脚
#ifndef S2P_DATA0
#define S2P_DATA0_PIN  GPIO_PIN_6
#define S2P_DATA0_PORT GPIOD
#endif
//定义芯片的串行输入以及时钟引脚
#ifndef S2P_DATA1
#define S2P_DATA1_PIN  GPIO_PIN_7
#define S2P_DATA1_PORT GPIOD
#endif
//定义芯片的串行输入以及时钟引脚
#ifndef S2P_DATA2
#define S2P_DATA2_PIN  GPIO_PIN_9
#define S2P_DATA2_PORT GPIOG
#endif
//定义芯片的串行输入以及时钟引脚
#ifndef S2P_DATA3
#define S2P_DATA3_PIN  GPIO_PIN_3
#define S2P_DATA3_PORT GPIOG
#endif

#ifndef S2P_RCLK
#define S2P_RCLK_PIN  GPIO_PIN_12
#define S2P_RCLK_PORT GPIOE
#endif

#ifndef S2P_LATCH
#define S2P_LATCH_PIN  GPIO_PIN_4
#define S2P_LATCH_PORT GPIOG
#endif

#ifndef S2P_OE
#define S2P_OE_PIN GPIO_PIN_15
#define S2P_OE_PORT GPIOE
#endif

#ifndef S2P_RESET
#define S2P_RESET_PIN GPIO_PIN_2
#define S2P_RESET_PORT GPIOG
#endif

#define HC595_CLK_H()  gpio_bit_set(S2P_RCLK_PORT,S2P_RCLK_PIN)
#define HC595_CLK_L()  gpio_bit_reset(S2P_RCLK_PORT,S2P_RCLK_PIN)

#define HC595_LATCH_H()  gpio_bit_set(S2P_LATCH_PORT,S2P_LATCH_PIN)
#define HC595_LATCH_L()  gpio_bit_reset(S2P_LATCH_PORT,S2P_LATCH_PIN)

#define HC595_DATA0_H()   gpio_bit_set(S2P_DATA0_PORT,S2P_DATA0_PIN);
#define HC595_DATA0_L()   gpio_bit_reset(S2P_DATA0_PORT,S2P_DATA0_PIN);

#define HC595_DATA1_H()   gpio_bit_set(S2P_DATA1_PORT,S2P_DATA1_PIN);
#define HC595_DATA1_L()   gpio_bit_reset(S2P_DATA1_PORT,S2P_DATA1_PIN);

#define HC595_DATA2_H()   gpio_bit_set(S2P_DATA2_PORT,S2P_DATA2_PIN);
#define HC595_DATA2_L()   gpio_bit_reset(S2P_DATA2_PORT,S2P_DATA2_PIN);

#define HC595_DATA3_H()   gpio_bit_set(S2P_DATA3_PORT,S2P_DATA3_PIN);
#define HC595_DATA3_L()   gpio_bit_reset(S2P_DATA3_PORT,S2P_DATA3_PIN);

#define HC595_OE_H() gpio_bit_set(S2P_OE_PORT,S2P_OE_PIN);
#define HC595_OE_L() gpio_bit_reset(S2P_OE_PORT,S2P_OE_PIN);

#define HC595_RESET_H() gpio_bit_set(S2P_RESET_PORT,S2P_RESET_PIN);
#define HC595_RESET_L() gpio_bit_reset(S2P_RESET_PORT,S2P_RESET_PIN);


#define S2P_DATA_OUT(port,pin,data) do {\
    if(data == 1) \
    {\
        gpio_bit_set(port,pin);\
    }\
    else \
    {\
        gpio_bit_reset(port,pin);\
    }\
}while(0)

#ifndef S2P_SHIFT_BIT
#define S2P_SHIFT_BIT(number,bit) do{ \
    switch(number)\
    {\
        case 0:\
            S2P_DATA_OUT(S2P_DATA0_PORT,S2P_DATA0_PIN,bit);\
            break;\
        case 1:\
            S2P_DATA_OUT(S2P_DATA1_PORT,S2P_DATA1_PIN,bit);\
            break;\
        case 2:\
            S2P_DATA_OUT(S2P_DATA2_PORT,S2P_DATA2_PIN,bit);\
            break;\
        case 3:\
            S2P_DATA_OUT(S2P_DATA3_PORT,S2P_DATA3_PIN,bit);\
            break;\
        default:\
        break;\
    }\
}while(0)
#endif

#ifndef S2P_WAIT_NOP
#define S2P_WAIT_NOP() do{ _nop_();_nop_();}while(0)
#endif

#ifdef S2P_EMIT_RISING_EDGE
#undef S2P_EMIT_RISING_EDGE
#endif
#define S2P_EMIT_RISING_EDGE(regit) do{\
    /*切换到低电平并保持两个周期*/\
    if(regit == 0)/*输入移位寄存器*/\
    {\
        S2P_DATA_OUT(S2P_RCLK_PORT,S2P_RCLK_PIN,0);\
    }\
    else \
    {   /*输出锁存寄存器*/\
        S2P_DATA_OUT(S2P_LATCH_PORT,S2P_LATCH_PIN,0);\
    }\
    /*切换到高电平（产生上升沿）并保存两个周期*/\
    if(regit == 0)/*输入移位寄存器*/\
    {\
        S2P_DATA_OUT(S2P_RCLK_PORT,S2P_RCLK_PIN,1);\
    }\
    else\
    {   /*输出锁存寄存器*/ \
        S2P_DATA_OUT(S2P_LATCH_PORT,S2P_LATCH_PIN,1);\
    } \
}while(0)

//定义输出移位寄存器时钟线上升沿的宏，方便外部功能在中断中进行调用
#ifndef S2P_SREDGE
#define S2P_SREDGE() S2P_EMIT_RISING_EDGE(0)
#endif

//定义输出锁存寄存器时钟线上升沿的宏，方便外部功能在中断中调用
#ifndef S2P_REDGE
#define S2P_REDGE() S2P_EMIT_RISING_EDGE(1)
#endif

extern void HC595_Run(void);

#endif
